package com.amex.uam.action;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;

import com.amex.uam.model.AMEX_BUSINESS;
import com.amex.uam.model.AMEX_UNIT;
import com.amex.uam.model.MS_USER_ADMIN;
import com.amex.uam.model.Message;
import com.amex.uam.model.USER_DEPT;
import com.amex.uam.service.AmexBusService;
import com.amex.uam.service.AmexUnitService;
import com.amex.uam.service.DeptService;
import com.amex.uam.service.GeoService;
import com.amex.uam.service.NotifyService;
import com.amex.uam.service.UserService;
import com.amex.uam.service.NotifyService.Action;
import com.amex.uam.service.NotifyService.Product;
import com.amex.uam.util.Utils;
import com.microstrategy.web.beans.RequestKeys;

@Controller("EPAAction")
public class EPAAction {

	public static boolean DEBUG = true;
	
	private UserService userService;
	private DeptService deptService;
	private AmexBusService amexBusService;
	private AmexUnitService amexUnitService;
	private GeoService geoService;
	private NotifyService notifyService;

	public EPAAction() {
		
	}
	
	@Resource
	public void setUserService(UserService userService) {
		this.userService = userService;
	}
	@Resource
	public void setDeptService(DeptService deptService) {
		this.deptService = deptService;
	}
	@Resource
	public void setAmexBusService(AmexBusService amexBusService) {
		this.amexBusService = amexBusService;
	}
	@Resource
	public void setAmexUnitService(AmexUnitService amexUnitService) {
		this.amexUnitService = amexUnitService;
	}
	@Resource
	public void setGeoService(GeoService geoService) {
		this.geoService = geoService;
	}
	@Resource
	public void setNotifyService(NotifyService notifyService) {
		this.notifyService = notifyService;
	}
	public Message registerUser(RequestKeys keys) {
		
		log("registerUser", "Enter method");
		try {
			// check if amexWebId exists
			boolean isExist = existsUserWithAmexWebId(keys);
			if (isExist == true) {
				return new Message(Message.ERROR, "This user already exists.");
			}
			
			/* **************************************/
			/* Register User General Information	*/
			/* **************************************/
			
			addDepartment(keys);
			addBusiness(keys);
			addAmexUnit(keys);
			
			addUser(keys);
			
			/* **************************************/
			/* Register User Type					*/ 					
			/* **************************************/
			
			addUserType(keys);
			
			/* ***************************************
			/* MicroStrategy Product 				*/
			/* **************************************/
			
			addMSTRProd(keys);
			
			/* **************************************/
			/* Register MARC Groups  				*/
			/* **************************************/
			
			addGMAPS(keys);// GMAPS
			addMarcFuncGroup(keys); // MARC Functional Group
			addOptBlue(keys);
			
			/* **************************************/
			/* Register Region and Country
			/* **************************************/
			if (isGlobal(keys)) {
				addUserRegion(keys);
				addUserCountry(keys);
			}
			
			/* **************************************/
			/* Notify Registration
			/* **************************************/
			notifyRegistration(keys);
			
		} catch (Throwable t) {
			t.printStackTrace();
			return new Message(Message.ERROR);
		}
		log("registerUser", "The End");
		
		return new Message(Message.OK);
	}
	
	private boolean isGlobal(RequestKeys keys) {
		String lifExcepRadio = val(keys, "lifExcepRadio");
		log("addUserRegion", "lifExcepRadio=" + lifExcepRadio);
		return "global".equals(lifExcepRadio);
	}
	
	public boolean addUserRegion(RequestKeys keys) {
		String lifExcepRegion = val(keys,"rcRgn");// region name list
		String amexWebId= val(keys,"amexWebId");
		
		log("addUserRegion", "amexWebId=" + amexWebId + ", rcRgn=" + lifExcepRegion);
		
		Message msg = geoService.addUserRegion(lifExcepRegion, amexWebId);
		return msg.getStatus() == Message.OK;
	}
	public boolean addUserCountry(RequestKeys keys) {
		String lifExcepCountry = val(keys,"rcCtry");// country name list
		String amexWebId= val(keys,"amexWebId");
		
		log("addUserCountry", "amexWebId=" + amexWebId + ", rcCtry=" + lifExcepCountry);
		
		Message msg = geoService.addUserCountry(lifExcepCountry, amexWebId);
		return msg.getStatus() == Message.OK;
	}
	public boolean addOptBlue(RequestKeys keys) {
		String amexWebId = val(keys,"amexWebId");
		String optBlueVal = val(keys,"optBlueRadio");// -1 indicates no access
		
		log("addOptBlue", "optBlueRadio=" + optBlueVal + ", amexWebId=" + amexWebId);
		
		if ("-1".equals(optBlueVal)) {
			optBlueVal = null;
		}
		 
		try {
			Message msg = this.userService.addUserGroup(amexWebId, optBlueVal);
			return msg.getStatus() == Message.OK;
		} catch (Throwable t) {
			t.printStackTrace();
			return false;
		}
		
	}

	public boolean addMarcFuncGroup(RequestKeys keys) {
		String amexWebId = val(keys, "amexWebId");
		String marcFuncVal = val(keys, "marcFuncRadio");

		log("addMarcFuncGroup", "marcFuncRadio=" + marcFuncVal + ", amexWebId=" + amexWebId);
		
		Message msg = this.userService.addMarcFuncGroup(amexWebId, marcFuncVal);
		return msg.getStatus() == Message.OK;
	}
	
	public boolean addGMAPS(RequestKeys keys) {
		String amexWebId = val(keys, "amexWebId");
		String gmapsVal = val(keys, "gmapsRadio");
		
		log("addGMAPS", "marcFuncRadio=" + gmapsVal + ", amexWebId=" + amexWebId);
		
		if ("-1".equals(gmapsVal)) {
			gmapsVal = null;
		}
		
		try {
			Message msg = this.userService.addUserGroup(amexWebId, gmapsVal);
			return msg.getStatus() == Message.OK;
		} catch (Throwable t) {
			t.printStackTrace();
			return false;
		}
	}

	public boolean existsUserWithAmexWebId(RequestKeys keys) {
		String amexWebId = val(keys, "amexWebId");
		log("existsUserWithAmexWebId", "amexWebId=" + amexWebId);
		
		Message user = userService.loadUserByAmexWebId(amexWebId);
		if (user.getStatus() == Message.OK && user.getData() != null) {
			return true;
		}
		return false;
	}
	
	// add user type
	public boolean addUserType(RequestKeys keys) {
		String amexWebId = val(keys, "amexWebId");
		String userTypeVal = val(keys, "usrTpRadio");
		log("addUserType", "usrTpRadio=" + userTypeVal + ", amexWebId=" + amexWebId);
		try {
			Message msg = userService.addUserGroup(amexWebId, userTypeVal);
			return msg.getStatus() == Message.OK; 
		} catch (Throwable t) {
			t.printStackTrace();
			return false;
		}
	}
	
	// add MicroStrategy Product
	public boolean addMSTRProd(RequestKeys keys) {
		String mstrProd = val(keys,"mstrProdOut");
		String amexWebId= val(keys,"amexWebId");
		log("addMSTRProd", "mstrProdOut=" + mstrProd + ", amexWebId=" + amexWebId);
		try{
			return userService.addMstrProd(mstrProd, amexWebId).getStatus() == Message.OK;
		} catch (Throwable t) {
			t.printStackTrace();
			return false;
		}
	}
	
	// add user general information
	public boolean addUser(RequestKeys keys) {
		MS_USER_ADMIN user = new MS_USER_ADMIN();
		
    	user.setUSER_ID(val(keys,"empId"));
    	user.setWORKFORCE_MBR_ID(val(keys,"amexWebId"));
		user.setDEPT_ID(val(keys,"deptId"));
		user.setAMEX_BUS_CD(val(keys,"bussUnitCD"));
		user.setUSER_EMAIL_AD_TX(val(keys,"emailAddr"));
		user.setWORKFORCE_MBR_MAN_1ST_NM(val(keys,"mFName"));
		user.setWORKFORCE_MBR_MAN_MI_TX(val(keys,"mMidInit"));
		user.setWORKFORCE_MBR_MAN_LST_NM(val(keys,"mLName"));
		user.setAMEX_UNIT_CD(val(keys,"amexUnitCD"));
		user.setCOST_CTR_CD(val(keys,"costCenter"));
		user.setUSER_CMPL_PHONE_NO(val(keys,"phone"));
		user.setWORKFORCE_MBR_MAN_EMAIL_AD_TX(val(keys,"mgrEmailAddr"));
		user.setVP_NM(val(keys,"VPName"));
		user.setUSER_1ST_NM(val(keys,"firstName"));
    	user.setUSER_MI_TX(val(keys,"midName"));
    	user.setUSER_LST_NM(val(keys,"lastName"));
		user.setACSS_RSN_TX(val(keys,"reason4Accs")); 
		user.setUSER_ACSS_TYPE_CD(val(keys, "accType"));
		//user.setCREAT_TS(cREAT_TS);
		
		
		log("addUser", user.toString());
		
		user.setLST_LOGIN_TS(new Timestamp(System.currentTimeMillis()));
    	user.setLST_UPDT_TS(new Timestamp(System.currentTimeMillis()));
    	user.setCREAT_TS(new Timestamp(System.currentTimeMillis()));
    	user.setSEC_XCPT_END_DT(new Timestamp(System.currentTimeMillis()));
    	
    	user.setNDA_TS(parseDate(val(keys, "accEndDate")));//Access End Date:
		
       	user.setUSER_ADMIN_STA_CD("0");
    	user.setUSER_STA_CD("0");
    	user.setUSER_GRP_ID(0);
    	user.setUSER_TYPE_CD("0");
    	user.setGEO_ACSS_LVL_CD("G");
    	user.setLIF_GLBL_ACS_IN("N");
    	user.setWORKFORCE_MBR_CLASS_CD("C");
    	user.setCLM_GLBL_ACS_IN("Y");
    	user.setUSER_ACSS_REJCT_RSN_TX("");
    	//user.setFUNC_GRP_ROLE_ID(keys.getValueCount("funtcRoleStep2"));
		
		Message msg = userService.addUser(user);
		return msg.getStatus() == Message.OK;
	}
	
	public boolean addDepartment(RequestKeys keys) {
		USER_DEPT dept = new USER_DEPT();
		dept.setDEPT_ID(val(keys, "deptId"));
		dept.setDEPT_NM(val(keys, "deptDesc"));
		log("addDepartment", "deptId=" + dept.getDEPT_ID() + ", deptDesc=" + dept.getDEPT_NM());
		
		Message msg = deptService.updateDepartment(dept);
		return msg.getStatus() == Message.OK;
	}
	
	public boolean addBusiness(RequestKeys keys) {
		AMEX_BUSINESS bus = new AMEX_BUSINESS();
		bus.setAMEX_BUS_CD(val(keys, "bussUnitCD"));
		bus.setAMEX_BUS_DS_TX(val(keys, "bussUnitDesc"));
		log("addBusiness", "bussUnitCD=" + bus.getAMEX_BUS_CD() + ", bussUnitDesc=" + bus.getAMEX_BUS_DS_TX());
		
		Message msg = amexBusService.updateBusiness(bus);
		return msg.getStatus() == Message.OK;
	}
	
	public boolean addAmexUnit(RequestKeys keys) {
		AMEX_UNIT unit = new AMEX_UNIT();
		unit.setAMEX_UNIT_CD(val(keys, "amexUnitCD"));
		unit.setAMEX_UNIT_DS_TX(val(keys, "amexUnitDesc"));
		log("addAmexUnit", "amexUnitCD=" + unit.getAMEX_UNIT_CD() + ", amexUnitDesc=" + unit.getAMEX_UNIT_DS_TX());
		
		Message msg = amexUnitService.updateAmexUnit(unit);
		return msg.getStatus() == Message.OK;
	}
	private Timestamp parseDate(String strDate) {
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy", Locale.US);
			return new Timestamp(sdf.parse(strDate).getTime());
		} catch(Throwable t) {
			return null;
		}
	}
	private String val(RequestKeys keys, String paramName) {
		return val(keys, paramName, null);
	}
	private String val(RequestKeys keys, String paramName, String defVal) {
		return Utils.trim(keys.getValue(paramName), defVal);
	}
	private void log(String methodName, String message) {
		if (DEBUG)
			System.out.println(this.getClass().getSimpleName() + "->" + methodName + ":  " + message);
	}
private void notifyRegistration(RequestKeys keys) {
		
		Map<String, String> params = new HashMap<String, String>();
		params.put("userId", Utils.trim(keys.getValue("userId"), ""));
		params.put("accessType", Utils.trim(keys.getValue("accType"), ""));
		params.put("costCenter", Utils.trim(keys.getValue("costCenter"), ""));
		params.put("reason", Utils.trim(keys.getValue("reason4Accs"), ""));
		params.put("middleInitial", Utils.trim(keys.getValue("midName"), ""));
		params.put("firstName", Utils.trim(keys.getValue("firstName"), ""));
		params.put("lastName", Utils.trim(keys.getValue("lastName"), ""));
		params.put("mFirstName", Utils.trim(keys.getValue("mFName"), ""));
		params.put("userEmail", Utils.trim(keys.getValue("emailAddr"), ""));
		params.put("managerEmail", Utils.trim(keys.getValue("mgrEmailAddr"), ""));
		
		String gmapsVal = Utils.trim(keys.getValue("gmapsRadio"), null);
		String optBlueVal = Utils.trim(keys.getValue("optBlueRadio"), null);
		
		List<Product> prod = new ArrayList<NotifyService.Product>();
		String mstrProdOut = Utils.trim(keys.getValue("mstrProdOut"), "");
		String[] arr = mstrProdOut.split(",");
		for (int i = 0; i < arr.length; i++) {
			int c = Utils.parseInt(arr[i], -1);
			switch (c) {
			case 1:
				prod.add(Product.MARC);
				break;
			case 2:
				prod.add(Product.Dashboard);
				break;
			case 3: 
				prod.add(Product.ICard);
				break;
			}
		}
		
		// Registration
		notifyService.asyncNotify(Action.Registration, prod, params);

		// OptBlue
		if (!"-1".equals(optBlueVal)){
			notifyService.asyncNotify(Action.OptBlue, prod, params);
		}
		
		// GMAPS
		if (!"-1".equals(gmapsVal)){
			notifyService.asyncNotify(Action.GMAPS, prod, params);	
		}
		
	}
}
